#include "modbusthread.hpp"
#include "threados.hpp"
#include "streamstation.hpp"
#include "uartstream.hpp"
#include "method.hpp"

#include "variable.hpp"
#include "app_config.h"
////> modbus 主要是用来进行控制的，主要通过寄存器操作
using namespace systemos;
using namespace protocols;
using namespace ota;

static stream::StreamPackTPDF mPack;
static stream *mDnSendStream;
static stream *mDnRecStream;
static stream *mUpSendStream;
static stream *mUpRecStream;

static protocolmodbus *mPSend;
static protocolmodbus *mPRec;
static WriteCommandTPDF mCommand;
static ota::firmwaredownload *mFirmwaredownload;

static bool WriteCallback_LcdCustomConfig(protocolmodbus::WriteDataAttributeTPDF *tWriteDataAttribute, uint16_t usLen);
static bool WriteCallback_Comconfig(protocolmodbus::WriteDataAttributeTPDF *tWriteDataAttribute, uint16_t usLen);
static bool WriteCallback_ControlCommand(protocolmodbus::WriteDataAttributeTPDF *tWriteDataAttribute, uint16_t usLen);
static bool WriteCallback_Calibration(protocolmodbus::WriteDataAttributeTPDF *tWriteDataAttribute, uint16_t usLen);
static bool CustomRegisterLimitCallBack(uint16_t usRegisterAddr, uint8_t *ucData, uint16_t usLen);


const protocolmodbus::RegisterAttributeTPDF mComConfigAttribute[] = 
{
	{true,	ComConfig_Addr_Attribute},
	{true,	ComConfig_Baud_Attribute,	CustomRegisterLimitCallBack},
};

const protocolmodbus::RegisterAttributeTPDF mCalibrationAttribute[] = 
{
	{true,	{2,	VARIABLE_TYPE_UINT16,	1,	{0,	65535}}},
};

const protocolmodbus::RegisterAttributeTPDF mControlCommandAttribute[] = 
{
	{true,	{2,	VARIABLE_TYPE_UINT16,	1,	{0,	65535}}},
};

const protocolmodbus::RegisterAttributeTPDF mLcdCustomConfigAttribute[] = 
{
	{true,	LcdCustomConfig_LongDelayCurrent_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_Distrib_LongDelayTime_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_Distrib_ShortDelayCurrent_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_Distrib_ShortDelayTime_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_Distrib_ShortCircuitCurrent_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_EarthCurrent_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_EarthTime_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_NCurrent_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_UnbalanceRated_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_UnbalanceTime_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_BlockCurrent_Attribute,	CustomRegisterLimitCallBack},
	{true,	LcdCustomConfig_BlockTime_Attribute, 0},
	{true,	LcdCustomConfig_LongDelayEnable_Attribute, 0},
	{true,	LcdCustomConfig_ShortDelayEnable_Attribute, 0},
	{true,	LcdCustomConfig_ShortCircuitEnable_Attribute, 0},
	{true,	LcdCustomConfig_NEnable_Attribute, 0},
	{true,	LcdCustomConfig_EarthEnable_Attribute, 0},
	{true,	LcdCustomConfig_UnbalanceEnable_Attribute, 0},
	{true,	LcdCustomConfig_BlockEnable_Attribute, 0},
	{true,	LcdCustomConfig_Frequnce_Attribute, 0},
};
///>modbus 控制的寄存器信息
static protocolmodbus::ModbusRegPartitionTPDF mLcdPartitionTable[] = 
{
	{protocolmodbus::REGISTER_READONLY,   ////> 读写权限
	 protocolmodbus::MODBUS_FUNCTION_READREG,  ///功能码
	 MODBUS_ADDR_MEASUREDATA,              ///add 
	 sizeof(MeasureDataPDF),              //size
	 (uint8_t*)&(mTarget.tMeasureData),   //source
	 0, 
	 0, 
	 0},
	{protocolmodbus::REGISTER_READONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_FAULTRECORD, 
	 sizeof(FaultRecordTPDF) * FAULT_RECORD_LEN, 
	 (uint8_t*)&(mTarget.tFaultRecord[0]), 
	 0, 
	 0, 
	 0},
	{protocolmodbus::REGISTER_READWRITE, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_COMCONFIG, 
	 sizeof(ComConfigTPDF), 
	 (uint8_t*)&(mTarget.tComConfig), 
	 mComConfigAttribute, 
	 sizeof(mComConfigAttribute) / sizeof(protocolmodbus::RegisterAttributeTPDF), 
	 WriteCallback_Comconfig},
	{protocolmodbus::REGISTER_READONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_MYPRODUCTINFOR, 
	 sizeof(MyProductInforTPDF), 
	 (uint8_t*)&(mTarget.tMyProductInfor), 
	 0, 
	 0, 
	 0},
	{protocolmodbus::REGISTER_READWRITE,  /// 读写
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_CUSTOMCONFIG,              
	 sizeof(LcdCustomConfigTPDF), 
	 (uint8_t*)&(mTarget.tLcdCustomConfig), 
	 mLcdCustomConfigAttribute,          ///> 寄存器属性
	 sizeof(mLcdCustomConfigAttribute) / sizeof(protocolmodbus::RegisterAttributeTPDF),//属性长度
	 WriteCallback_LcdCustomConfig}, 

	{protocolmodbus::REGISTER_WRITEONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_CONTROLCOMMAND, 
	 sizeof(ControlCommandTPDF), 
	 0,
	 mControlCommandAttribute, 
	 sizeof(mControlCommandAttribute) / sizeof(protocolmodbus::RegisterAttributeTPDF),
	 WriteCallback_ControlCommand},
	{protocolmodbus::REGISTER_WRITEONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 0x3000, 
	 2,
	 0, 
	 mCalibrationAttribute, 
	 sizeof(mCalibrationAttribute) / sizeof(protocolmodbus::RegisterAttributeTPDF),
	 WriteCallback_Calibration}, 
};

static protocolmodbus::ModbusRegPartitionTPDF mSwitchPartitionTable[] = 
{
	{protocolmodbus::REGISTER_READONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_MEASUREDATA, 
	 sizeof(MeasureDataPDF), 
	 (uint8_t*)&(mTarget.tMeasureData), 
	 0, 
	 0, 
	 0},
	{protocolmodbus::REGISTER_READONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_FAULTRECORD, 
	 sizeof(FaultRecordTPDF) * FAULT_RECORD_LEN, 
	 (uint8_t*)&(mTarget.tFaultRecord[0]), 
	 0, 
	 0, 
	 0},
	{protocolmodbus::REGISTER_READWRITE, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_COMCONFIG, 
	 sizeof(ComConfigTPDF), 
	 (uint8_t*)&(mTarget.tComConfig), 
	 mComConfigAttribute, 
	 sizeof(mComConfigAttribute) / sizeof(protocolmodbus::RegisterAttributeTPDF),
	 WriteCallback_Comconfig},
	{protocolmodbus::REGISTER_READONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_MYPRODUCTINFOR, 
	 sizeof(MyProductInforTPDF), 
	 (uint8_t*)&(mTarget.tMyProductInfor), 
	 0, 
	 0, 
	 0},
	{protocolmodbus::REGISTER_READONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_CUSTOMCONFIG, 
	 sizeof(SwitchCustomConfigTPDF),
	 (uint8_t*)&(mTarget.tSwitchCustomConfig), 
	 0, 
	 0,
	 0}, 
	{protocolmodbus::REGISTER_WRITEONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 MODBUS_ADDR_CONTROLCOMMAND, 
	 sizeof(ControlCommandTPDF), 
	 0,
	 mControlCommandAttribute, 
	 sizeof(mControlCommandAttribute) / sizeof(protocolmodbus::RegisterAttributeTPDF), 
	 WriteCallback_ControlCommand},
	{protocolmodbus::REGISTER_WRITEONLY, 
	 protocolmodbus::MODBUS_FUNCTION_READREG,
	 0x3000, 
	 2,
	 0, 
	 mCalibrationAttribute, 
	 sizeof(mCalibrationAttribute) / sizeof(protocolmodbus::RegisterAttributeTPDF),
	 WriteCallback_Calibration}, 
};

static bool QueueExchange(void)
{
	WriteStatusTPDF tWriteStatus;
	uint16_t n = 1000;
	
	mUpSendStream->Public(&mCommand);
	while(!mUpRecStream->Subscribe(&tWriteStatus))
	{
		Method::Sleep(1);
		n--;
		if(n <= 0)
		{
			break;
		}
	}
	return(tWriteStatus.bResult);
}
///>  写寄存器值判断
static bool CustomRegisterLimitCallBack(uint16_t usRegisterAddr, uint8_t *ucData, uint16_t usLen)
{
	uint32_t i = (ucData[0] << 8) + ucData[1];
	uint32_t In = mTarget.tProductInfor.usCurrent;
	uint32_t Ir = mTarget.tLcdCustomConfig.usLongDelayCurrent;
	
	switch(usRegisterAddr)
	{
		case 0x0101:
			if(i == 9600 || i == 19200)//uint16_t usBaud;								///<波特率
			{
				return(true);
			}
			return(false);
		default:
			break;
	}
	switch(mTarget.tProductInfor.usAttribute & 0x01)
	{
		case 0:	///<LCD配电型
			switch(usRegisterAddr)
			{
				case 0x2007:
					if(i >= (In * LcdCustomConfig_LongDelayCurrent_Attribute.tVariableDataLimit.iLower / 100) &&
						i <= (In * LcdCustomConfig_LongDelayCurrent_Attribute.tVariableDataLimit.iUpper /100))
					{
						return(true);
					}
					return(false);
				case 0x2008:
					if(i >= (LcdCustomConfig_Distrib_LongDelayTime_Attribute.tVariableDataLimit.iLower) &&
						i <= (LcdCustomConfig_Distrib_LongDelayTime_Attribute.tVariableDataLimit.iUpper))
					{
						return(true);
					}
					return(false);
				case 0x2009:
					if(i >= (Ir * LcdCustomConfig_Distrib_ShortDelayCurrent_Attribute.tVariableDataLimit.iLower / 100) &&
						i <= (Ir * LcdCustomConfig_Distrib_ShortDelayCurrent_Attribute.tVariableDataLimit.iUpper /100))
					{
						return(true);
					}
					return(false);
				case 0x200a:
					if(i == 100 || i == 200 || i == 300 || i == 400)
					{
						return(true);
					}
					return(false);
				case 0x200b:
					if(i >= (In * LcdCustomConfig_Distrib_ShortCircuitCurrent_Attribute.tVariableDataLimit.iLower / 100) &&
						 i <= (In* LcdCustomConfig_Distrib_ShortCircuitCurrent_Attribute.tVariableDataLimit.iUpper / 100))
					{
						return(true);
					}
					return(false);
				case 0x200c:
					if(i >= (In * LcdCustomConfig_EarthCurrent_Attribute.tVariableDataLimit.iLower /100) &&
						 i <= (In * LcdCustomConfig_EarthCurrent_Attribute.tVariableDataLimit.iUpper / 100))
					{
						return(true);
					}
					return(false);
				case 0x200d:
					if(i == 100 || i == 200 || i == 300 || i == 400)
					{
						return(true);
					}
					return(false);
				case 0x200e:
					if(i == 5 || i == 10)
					{
						return(true);
					}
					return(false);
				case 0x200f:
					if(i >= (LcdCustomConfig_UnbalanceRated_Attribute.tVariableDataLimit.iLower) &&
						 i <= (LcdCustomConfig_UnbalanceRated_Attribute.tVariableDataLimit.iUpper))
					{
						return(true);
					}
					return(false);
				case 0x2010:
					if(i == 4 || i == 6 || i == 8 || i == 10)
					{
						return(true);
					}
					return(false);
				case 0x2011:
					if(i >= (Ir * LcdCustomConfig_BlockCurrent_Attribute.tVariableDataLimit.iLower / 100) &&
						 i <= (Ir * LcdCustomConfig_BlockCurrent_Attribute.tVariableDataLimit.iUpper / 100))
					{
						return(true);
					}
					return(false);
				default:
					break;
			}
			break;
		case 1:	///<LCD电机型
			switch(usRegisterAddr)
			{
				case 0x2007:
					if(i >= (In * LcdCustomConfig_LongDelayCurrent_Attribute.tVariableDataLimit.iLower / 100) &&
						i <= (In * LcdCustomConfig_LongDelayCurrent_Attribute.tVariableDataLimit.iUpper /100))
					{
						return(true);
					}
					return(false);
				case 0x2008:
					if(i == 5 || i == 10 || i == 20 || i == 30)
					{
						return(true);
					}
					return(false);
				case 0x2009:
					if(i >= (Ir * LcdCustomConfig_Motor_ShortDelayCurrent_Attribute.tVariableDataLimit.iLower / 100) &&
						i <= (Ir * LcdCustomConfig_Motor_ShortDelayCurrent_Attribute.tVariableDataLimit.iUpper /100))
					{
						return(true);
					}
					return(false);
				case 0x200a:
					if(i == 100)
					{
						return(true);
					}
					return(false);
				case 0x200b:
					if(i >= (In * LcdCustomConfig_Motor_ShortCircuitCurrent_Attribute.tVariableDataLimit.iLower / 100) &&
						 i <= (In * LcdCustomConfig_Motor_ShortCircuitCurrent_Attribute.tVariableDataLimit.iUpper / 100))
					{
						return(true);
					}
					return(false);
				case 0x200c:
					if(i >= (In * LcdCustomConfig_EarthCurrent_Attribute.tVariableDataLimit.iUpper /100) &&
						 i <= (In * LcdCustomConfig_EarthCurrent_Attribute.tVariableDataLimit.iLower / 100))
					{
						return(true);
					}
					return(false);
				case 0x200d:
					if(i == 100 || i == 200 || i == 300 || i == 400)
					{
						return(true);
					}
					return(false);
				case 0x200e:
					if(i == 5 || i == 10)
					{
						return(true);
					}
					return(false);
				case 0x200f:
					if(i >= (LcdCustomConfig_UnbalanceRated_Attribute.tVariableDataLimit.iLower) &&
						 i <= (LcdCustomConfig_UnbalanceRated_Attribute.tVariableDataLimit.iUpper))
					{
						return(true);
					}
					return(false);
				case 0x2010:
					if(i == 4 || i == 6 || i == 8 || i == 10)
					{
						return(true);
					}
					return(false);
				case 0x2011:
					if(i >= (Ir * LcdCustomConfig_BlockCurrent_Attribute.tVariableDataLimit.iLower / 100) &&
						 i <= (Ir * LcdCustomConfig_BlockCurrent_Attribute.tVariableDataLimit.iUpper / 100))
					{
						return(true);
					}
					return(false);
				default:
					break;
			}
			break;
	}
	return(false);
}
///> 写回调函数用于内部数据流写
static bool WriteCallback_Calibration(protocolmodbus::WriteDataAttributeTPDF *tWriteDataAttribute, uint16_t usLen)
{
	if(usLen == 1 && tWriteDataAttribute->usLen == 2 && tWriteDataAttribute->ucData[0] == 0x00 &&  tWriteDataAttribute->ucData[1] == 0xff)
	{
		mCommand.usLen = 1;
		mCommand.tType = WRITE_COMMAND_CALIBRATION;
		return(QueueExchange());
	}
	return(false);
}
static bool WriteCallback_LcdCustomConfig(protocolmodbus::WriteDataAttributeTPDF *tWriteDataAttribute, uint16_t usLen)
{
	uint16_t i;
	
	for(i = 0; i < usLen; i++)
	{
		memcpy(mCommand.tWriteData[i].ucData, tWriteDataAttribute[i].ucData, tWriteDataAttribute[i].usLen);
		mCommand.tWriteData[i].usLen = tWriteDataAttribute[i].usLen;
		mCommand.tWriteData[i].usOffset = tWriteDataAttribute[i].usResourceOffset;
		mCommand.tWriteData[i].uiKey = tWriteDataAttribute[i].iKey;
	}
	mCommand.usLen = usLen;
	mCommand.tType = WRITE_COMMAND_CUSTOMCONFIG;
	return(QueueExchange());
}

static bool WriteCallback_Comconfig(protocolmodbus::WriteDataAttributeTPDF *tWriteDataAttribute, uint16_t usLen)
{
	uint16_t i;
	
	for(i = 0; i < usLen; i++)
	{
		memcpy(mCommand.tWriteData[i].ucData, tWriteDataAttribute[i].ucData, tWriteDataAttribute[i].usLen);
		mCommand.tWriteData[i].usLen = tWriteDataAttribute[i].usLen;
		mCommand.tWriteData[i].usOffset = tWriteDataAttribute[i].usResourceOffset;
		mCommand.tWriteData[i].uiKey = tWriteDataAttribute[i].iKey;
	}
	mCommand.usLen = usLen;
	mCommand.tType = WRITE_COMMAND_COMCONFIG;
	return(QueueExchange()); ///内部数据传输
}

static bool WriteCallback_ControlCommand(protocolmodbus::WriteDataAttributeTPDF *tWriteDataAttribute, uint16_t usLen)
{
	mCommand.tWriteData[0].usLen = 2;
	mCommand.tWriteData[0].ucData[0] = tWriteDataAttribute->ucData[0];
	mCommand.tWriteData[0].ucData[1] = tWriteDataAttribute->ucData[1];
	mCommand.tWriteData[0].usOffset = 0;
	mCommand.tWriteData[0].uiKey = tWriteDataAttribute[0].iKey;
	mCommand.usLen = 1;
	mCommand.tType = WRITE_COMMAND_CONTROL;
	return(QueueExchange());
}
///特殊命令回调函数
static bool WriteCallback_Specmd(uint8_t ucSlaveAddr, uint16_t tCommand, uint8_t *ucData, uint16_t usLen)
{  ///>写厂家信息
	switch(tCommand)
	{
		case 0x09:
			mCommand.tType = WRITE_COMMAND_RESET;
			return(QueueExchange());
		case 0xFF00: //写SN
			if(usLen == 24)
			{
				memcpy(mCommand.tWriteData[0].ucData, ucData, 24);
				mCommand.tWriteData[0].uiKey = ProtectInfor_SN_Attribute.uiKey;
				mCommand.tWriteData[0].usLen = 24;
				mCommand.tWriteData[0].usOffset = 0;
				mCommand.usLen = 1;
				mCommand.tType = WRITE_COMMAND_PRODUCTINFOR;
				return(QueueExchange());
			}
			else
			{
				return(false);
			}
		case 0xFF01:
			if(usLen == 28)
			{
				mCommand.tWriteData[0].uiKey = ProtectInfor_ManufactoryId_Attribute.uiKey;
				mCommand.tWriteData[0].ucData[0] = ucData[0];
				mCommand.tWriteData[0].usLen = 1;
				mCommand.tWriteData[0].usOffset = 0;
				mCommand.tWriteData[1].uiKey = ProtectInfor_Class_Attribute.uiKey;
				mCommand.tWriteData[1].ucData[0] = ucData[1];
				mCommand.tWriteData[1].usLen = 1;
				mCommand.tWriteData[1].usOffset = 0;
				mCommand.tWriteData[2].uiKey = ProtectInfor_Serial_Attribute.uiKey;
				mCommand.tWriteData[2].ucData[0] = ucData[2];
				mCommand.tWriteData[2].usLen = 1;
				mCommand.tWriteData[2].usOffset = 0;
				mCommand.tWriteData[3].uiKey = ProtectInfor_PriSerial_Attribute.uiKey;
				mCommand.tWriteData[3].ucData[0] = ucData[3];
				mCommand.tWriteData[3].usLen = 1;
				mCommand.tWriteData[3].usOffset = 0;
				mCommand.tWriteData[4].uiKey = ProtectInfor_HardwareSerial_Attribute.uiKey;
				mCommand.tWriteData[4].ucData[0] = ucData[5];
				mCommand.tWriteData[4].ucData[1] = ucData[4];
				mCommand.tWriteData[4].usLen = 2;
				mCommand.tWriteData[4].usOffset = 0;
				mCommand.tWriteData[5].uiKey = ProtectInfor_Current_Attribute.uiKey;
				mCommand.tWriteData[5].ucData[0] = ucData[7];
				mCommand.tWriteData[5].ucData[1] = ucData[6];
				mCommand.tWriteData[5].usLen = 2;
				mCommand.tWriteData[5].usOffset = 0;
				mCommand.tWriteData[6].uiKey = ProtectInfor_StructCurrent_Attribute.uiKey;
				mCommand.tWriteData[6].ucData[0] = ucData[9];
				mCommand.tWriteData[6].ucData[1] = ucData[8];
				mCommand.tWriteData[6].usLen = 2;
				mCommand.tWriteData[6].usOffset = 0;
				mCommand.tWriteData[7].uiKey = ProtectInfor_Attribute_Attribute.uiKey;
				mCommand.tWriteData[7].ucData[0] = ucData[11];
				mCommand.tWriteData[7].ucData[1] = ucData[10];
				mCommand.tWriteData[7].usLen = 2;
				mCommand.tWriteData[7].usOffset = 0;
				mCommand.tWriteData[8].uiKey = ProtectInfor_SoftDescription_Attribute.uiKey;
				memcpy(mCommand.tWriteData[8].ucData, ucData + 12, 16);
				mCommand.tWriteData[8].usLen = 16;
				mCommand.tWriteData[8].usOffset = 0;
				mCommand.usLen = 9;
				mCommand.tType = WRITE_COMMAND_PRODUCTINFOR;
				return(QueueExchange());
			}
			else
			{
				return(false);
			}
		case 0xFF02:
			mCommand.tType = WRITE_COMMAND_CALIBRATION;
			return(QueueExchange());
			break;
		default:
			break;
	}
	return(false);
}
///> 广播回调函数，不处理
static bool BroadCastCallback(protocolmodbus *tprotocol)
{
	return(false);
}
///> 从站回复函数
static uint8_t RequestCallback_Report(uint8_t *ucData)
{
	firmwaredownload::FirmWareInforTPDF tInf;
	
	mFirmwaredownload->ReadPrgInfor(&tInf);
	ucData[0] = mTarget.tProductInfor.ucManufactoryId;
	ucData[1] = mTarget.tProductInfor.ucClass;
	ucData[2] = mTarget.tProductInfor.ucSerial;
	ucData[3] = mTarget.tProductInfor.ucPriSerial;
	ucData[4] = 0;
	ucData[5] = (tInf.uiNewVersion >> 8) & 0x000000ff;
	ucData[6] = tInf.uiNewVersion & 0x000000ff;
	ucData[7] = mTarget.tProductInfor.ucHardwareSerial[0];
	ucData[8] = mTarget.tProductInfor.ucHardwareSerial[1];
	for(uint8_t i = 0; i < 24; i++)
	{
		ucData[9 + i] = mTarget.tProductInfor.ucSN[i];
	}
	for(uint8_t i = 0; i < 12; i++)
	{
		ucData[33 + i * 2] = 0;
		ucData[33 + i * 2 + 1] = 0;
	}
	return(0x39);
}

static void ModbusThread(void *args)
{
	while(1)
	{
		Method::Sleep(1);
		if(mDnRecStream->Subscribe(&mPack)) ///> 对串口通讯
		{
			if(!mPRec->Unpack(mPack.ucBuff, mPack.usLen))  ///协议拆包分解保存数据成功
			{
				continue;
			}
			if(mPRec->SlaveAddr == 0xfa)
			{
				mPRec->SlaveAddr = mTarget.tComConfig.usAddr;
			}
			if(mPRec->Map(mPSend, mTarget.tComConfig.usAddr))
			{
				mPSend->SlaveAddr = mTarget.tComConfig.usAddr;
				mPack.usLen = mPSend->Pack(mPack.ucBuff);
				mDnSendStream->Public(&mPack); ///> 串口读数据返回对串口数据流
			}
		}
	}
}

void ModbusThreadInit(ota::firmwaredownload *tfirmwaredownload)
{
	mDnSendStream = new stream(MODBUSTHREAD_DN_PUBLIC_NAME, stream::STREAM_DIRECT_PUBLIC, sizeof(stream::StreamPackTPDF));///> 对串口通讯
	mDnRecStream = new stream(MODBUSTHREAD_DN_SUBSCRIBE_NAME, stream::STREAM_DIRECT_SUBSCRIBE, sizeof(stream::StreamPackTPDF));
	mUpSendStream = new stream(MODBUSTHREAD_UP_PUBLIC_NAME, stream::STREAM_DIRECT_PUBLIC, sizeof(WriteCommandTPDF));///> 对内部通讯
	mUpRecStream = new stream(MODBUSTHREAD_UP_SUBSCRIBE_NAME, stream::STREAM_DIRECT_SUBSCRIBE, sizeof(WriteStatusTPDF));
	
	mPSend = new protocolmodbus();
	mPRec = new protocolmodbus();
	
	mPRec->BroadCastAddr = 0xff;
	mFirmwaredownload = tfirmwaredownload;
	mPRec->RegisteOtaInterface(tfirmwaredownload);
	if(mTarget.tProductInfor.usAttribute & CONFIG_ATTRIBUTE_FLAG_SWITCH)
	{
		mPRec->RegistePartitionTable(&mSwitchPartitionTable[0],sizeof(mSwitchPartitionTable) / sizeof (                   protocolmodbus::ModbusRegPartitionTPDF));
	}   
	else
	{
		mPRec->RegistePartitionTable(&mLcdPartitionTable[0],sizeof(mLcdPartitionTable) / sizeof(protocolmodbus::ModbusRegPartitionTPDF));
	}
	mPRec->SpeOrderCallBack = WriteCallback_Specmd;
	mPRec->RequestReportDataCallBack = RequestCallback_Report;
	mPRec->BroadCastCallBack = BroadCastCallback;
	
	threados *t1 = new threados(ModbusThread);
	t1->Name = "modbus";
	t1->Prio = 0;
	t1->StackDeep = 256;
	t1->Start();
}
